package com.wh1200.mybatis.xmlless.model

import com.wh1200.mybatis.xmlless.model.base.BaseTableFieldWrapper
import com.wh1200.mybatis.xmlless.util.ColumnUtils
import net.sf.jsqlparser.expression.CastExpression
import net.sf.jsqlparser.expression.JsonExpression
import net.sf.jsqlparser.expression.Parenthesis
import net.sf.jsqlparser.parser.CCJSqlParserUtil
import net.sf.jsqlparser.schema.Column
import net.sf.jsqlparser.schema.Table


/**
 * Created by 吴昊 on 2018/12/12.
 */
class SelectColumn(
    val fieldWrapper: BaseTableFieldWrapper?,
    val table: TableName?,
    val column: String,
    val alias: String?,
    private val function: String? = null,
    val middleTables: List<TableName> = listOf()
) {

  init {
    if (alias != null && alias.contains(".")) {
      error("字段${column}使用的了非法的别名：${alias}")
    }
  }

  fun toSqlWithoutAlias(): String {
    fun getColumnStr(): String {
      val ps = CCJSqlParserUtil.parseExpression(column)
      if (ps is CastExpression) {
        val left = ps.leftExpression
        if (left is Parenthesis) {
          val expression = left.expression
          if (expression is JsonExpression) {
            val exp = expression.expression
            if (exp is Column && table != null) {
              exp.table = Table(table.getAliasOrName())
              return ps.toString()
            }
          }
        }
      }
      return when {
        table != null -> String.format("%s.%s", table.getAliasOrName(), ColumnUtils.wrapColumn(column))
        else          -> ColumnUtils.wrapColumn(column)
      }
    }

    val str = getColumnStr()
    if (function != null) {
      return "$function($str)"
    }
    return str
  }


  fun toSql(): String {
    val str = when {
      table != null -> when {
        alias != null -> String.format(
            "%s.%s AS %s", table.getAliasOrName(),
            ColumnUtils.wrapColumn(column),
            ColumnUtils.wrapColumn(alias)
        )

        else          -> String.format("%s.%s", table.getAliasOrName(), ColumnUtils.wrapColumn(column))
      }

      else          -> when {
        alias != null -> String.format("%s AS %s", ColumnUtils.wrapColumn(column),
            ColumnUtils.wrapColumn(alias))
        else          -> ColumnUtils.wrapColumn(column)
      }
    }
    if (function != null) {
      return "$function($str)"
    }
    return str
  }

  override fun toString(): String {
    return toSql()
  }

}
